package com.bungarus.group.config;

import io.shardingsphere.api.config.rule.ShardingRuleConfiguration;
import io.shardingsphere.api.config.rule.TableRuleConfiguration;
import io.shardingsphere.api.config.strategy.InlineShardingStrategyConfiguration;
import io.shardingsphere.shardingjdbc.api.ShardingDataSourceFactory;
import org.apache.commons.dbcp2.BasicDataSource;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;

import javax.sql.DataSource;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;

@Configuration
public class ShardingConfig {

    @ConfigurationProperties(prefix = "sharding.jdbc.datasource.ds0")
    @Bean(name = "ds0")
    public DataSource dataSource0() {
        return new BasicDataSource();
    }


    @Primary
    @ConditionalOnMissingBean
    @Bean(name = "shardingDataSource")
    public DataSource getDataSource(@Qualifier("ds0") DataSource ds0) throws SQLException {
        Map dataSourceMap =new HashMap<>();
        dataSourceMap.put("ds0", ds0);

        ShardingRuleConfiguration shardingRuleConfig =new ShardingRuleConfiguration();
        shardingRuleConfig.getTableRuleConfigs().add(getMemberGroupTableRuleConfiguration());
        shardingRuleConfig.getTableRuleConfigs().add(getGroupMemberTableRuleConfiguration());

        DataSource dataSource = ShardingDataSourceFactory.createDataSource(dataSourceMap, shardingRuleConfig,new ConcurrentHashMap(),new Properties());
        return dataSource;
    }

    /**
     * Member-Group mapping sharding rule config
     * @return
     */
    private static TableRuleConfiguration getMemberGroupTableRuleConfiguration() {
        TableRuleConfiguration memberGroupTableRuleConfig =new TableRuleConfiguration();
        memberGroupTableRuleConfig.setLogicTable("t_member_group");
        memberGroupTableRuleConfig.setActualDataNodes("ds0.t_member_group_${0..9}");
        memberGroupTableRuleConfig.setDatabaseShardingStrategyConfig(new InlineShardingStrategyConfiguration("mid","ds0"));
        memberGroupTableRuleConfig.setTableShardingStrategyConfig(new InlineShardingStrategyConfiguration("mid","t_member_group_${mid % 10}"));
        return memberGroupTableRuleConfig;
    }

    /**
     * Group-Member mapping sharding rule config
     * @return
     */
    private static TableRuleConfiguration getGroupMemberTableRuleConfiguration() {
        TableRuleConfiguration groupMemberTableRuleConfig =new TableRuleConfiguration();
        groupMemberTableRuleConfig.setLogicTable("t_group_member");
        groupMemberTableRuleConfig.setActualDataNodes("ds0.t_group_member_${0..9}");
        groupMemberTableRuleConfig.setDatabaseShardingStrategyConfig(new InlineShardingStrategyConfiguration("gid","ds0"));
        groupMemberTableRuleConfig.setTableShardingStrategyConfig(new InlineShardingStrategyConfiguration("gid","t_group_member_${gid % 10}"));
        return groupMemberTableRuleConfig;
    }
}
